/* To learn more about opengl for c++ go to www.videotutorialsrock.com
   To run this program: compile by typing "make" into the terminal and    
   then "./main" to run.
*/


#include <iostream>
#include <math.h>
#include <vector>
#include <stdlib.h> //Needed for "exit" function
#include "Points.h"
#include <sstream>

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

using namespace std;

//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
					int x, int y) {    //The current mouse coordinates
	switch (key) {
		case 27: //Escape key
			exit(0); //Exit the program
	}
}

//Initializes 3D rendering
void initRendering() {
	//Makes 3D drawing work when something is in front of something else
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	//enable color
	glEnable(GL_COLOR_MATERIAL);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}

//Called when the window is resized
void handleResize(int w, int h) {
	//Tell OpenGL how to convert from coordinates to pixel values
	glViewport(0, 0, w, h);
	
	glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
	
	//Set the camera perspective
	glLoadIdentity(); //Reset the camera
	gluPerspective(45.0,                  //The camera angle
		       (double)w / (double)h, //The width-to-height ratio
		       1.0,                   //The near z clipping coordinate
		       200.0);                //The far z clipping coordinate
}

//Decides what color the line segments should be.
void colors(float& red, float& green, float& blue, int count) {
	float colorPercent;
	if(count <= 300) {
		red = 1.0;
		green = 0;
		blue = 0;
	}
	else if(count > 300 && count <= 4500) {
		colorPercent = (count-300.0)/4200.0;
		red = 1.38 - colorPercent;
		green = colorPercent - 0.62;
		blue = colorPercent - 0.62;
	}
	else if(count > 4500) {
		red = 0.38;
		green = 0.38;
		blue = 0.38;
	}
}

vector <Points> allPoints; //Stores all the points for plotting

void draw() {
	glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
	glLoadIdentity(); //Reset the drawing perspective
	
	glColor3f(0.42f,0.48f,0.55f);
	glLineWidth(1.0);
	glBegin(GL_LINES); //Begin line coordinates
	
	//horizontal
	glVertex3f(-1.0f, 0.0f, -4.0f);
	glVertex3f(1.0f, 0.0f, -4.0f);
	//vertical
	glVertex3f(0.0f, -1.0f, -4.0f);
	glVertex3f(0.0f, 1.0f, -4.0f);
	//Diagonal
	glVertex3f(-(1.0f/sqrt(2.0f)), -(1.0f/sqrt(2.0f)), -4.0f);
	glVertex3f(1.0f/sqrt(2.0f), 1.0f/sqrt(2.0f), -4.0f);
	
	glVertex3f(-(1.0f/sqrt(2.0f)), 1.0f/sqrt(2.0f), -4.0f);
	glVertex3f(1.0f/sqrt(2.0f), -(1.0f/sqrt(2.0f)), -4.0f);
	
	glEnd(); //End line coordinates
	
	glBegin(GL_LINE_LOOP); //Creates a circle.
	for (double i = 0; i <= 2*M_PI; i+= 0.01)
		glVertex3f(cos(i), sin(i), -4.0f);
	glEnd();
	
	//Draw points (more like little line segments.
	glLineWidth(2.0f);
	glShadeModel(GL_SMOOTH);
	glBegin(GL_LINE_STRIP);
	for(unsigned int i = 0; i < allPoints.size(); ++i) {
		float R = 0.0;
		float G = 0.0;
		float B = 0.0;
		int count = allPoints.size() - i;
		colors(R, G, B, count); //Calculate the color.
		glColor3f(R, G, B);	
		glVertex3f(allPoints[i].getX(), allPoints[i].getY(), -4.0f);
	}
	glEnd(); //End point drawing
}

//Draws the 3D scene. Draw lines to make a graph
void drawScene() {	
	//Show the frames on the screen
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	draw();

	glutSwapBuffers(); //Send the 3D scene to the screen
}

void updatePoints() {
	static double angle = 0.0;

	if(angle <= 86.0) {
		//Adjutsts how many points you want add to the Vector at once
		//with the for loop. By doing so, it adjusts the plotting speed.
		for(unsigned int i = 0; i < 30; ++i) { 
			double x, y, radius;
			radius = cos(M_PI*angle);
			x = radius*cos(angle);
			y = radius*sin(angle);
			Points aPoint(x, y, angle);
			allPoints.push_back(aPoint);
			angle+=0.01;
		}
	}
	return;
}

void animate(int value) {
	updatePoints();
	glutPostRedisplay();
	glutTimerFunc(30, animate, 0); //Draw frames with delay, so it looks animated
}

int main(int argc, char** argv) {
	//Initialize GLUT
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(750, 800); //Set the window size
	
	//Create the window
	glutCreateWindow("Polar Graph");
	initRendering(); //Initialize rendering
	
	//Set handler functions for drawing, keypresses, and window resizes
	glutDisplayFunc(drawScene);
	glutTimerFunc(30, animate, 0); 
	glutKeyboardFunc(handleKeypress);
	glutReshapeFunc(handleResize);
	
	glutMainLoop(); //Start the main loop.  glutMainLoop doesn't return.
	return 0; 
}









